﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace nl.hanze.i.web.t41
{
    class Mens
    {
        private String naam;
        private DateTime geboortedatum;
        private long bsn;
        private Sexe geslacht;
        private static long laatstebsn = 111222333;

        // Alleen nummers accepteren. Moet tussen 1 en 15 cijfers zijn.
        private Regex bsnRegex = new Regex("^[0-9]{1,15}$");

        /// <summary>
        /// Default constructor roept een volgende constructor aan met default waarden
        /// </summary>
        public Mens()
            : this("John Doe", Mens.getNieuweGeboorteDatum(), Sexe.Man)
        {            
        }

        /// <summary>
        /// "Master"-constructor die de daadwerkelijke variabelen zet.
        /// </summary>
        /// <param name="naam"></param>
        /// <param name="geboortedatum"></param>
        /// <param name="geslacht"></param>
        public Mens(String naam, DateTime geboortedatum, Sexe geslacht)
        {
            this.naam = naam;
            this.geboortedatum = geboortedatum;
            this.geslacht = geslacht;
            //variabele direct zetten
            this.Bsn = Convert.ToString(Mens.laatstebsn);
            Mens.laatstebsn++;
        }

        //
        // Methods
        //

        /// <summary>
        /// Vraag leeftijd op van Mens. Methode gebaseerd op:
        /// http://stackoverflow.com/a/1404/921154
        /// </summary>
        /// <returns></returns>
        public int getLeeftijd()
        {
            DateTime now = DateTime.Today;
            int leeftijd = now.Year - geboortedatum.Year;
            if (geboortedatum.Date > now.AddYears(-leeftijd).Date)
            {
                leeftijd--;
            }

            return leeftijd;
        }

        //
        // Operators
        //

        /// <summary>
        /// Twee Mensen kunnen opgeteld worden.
        /// 
        /// Geboortedatum is 9 maanden +/- 2 weken van moment van optelling.
        /// 
        /// Er wordt een GeenZwangerschapMogelijkException gegooid wanneer:
        /// - hetzelfde geslacht
        /// - minimaal 1 leeftijd onder de 16
        /// </summary>
        /// <param name="mens1"></param>
        /// <param name="mens2"></param>
        /// <returns></returns>
        public static Mens operator +(Mens mens1, Mens mens2)
        {
            if (mens1.getLeeftijd() < 16 || mens2.getLeeftijd() < 16)
            {
                throw new GeenZwangerschapMogelijkException("Mensen jonger dan ");
            }

            if (mens1.Geslacht.Equals(mens2.Geslacht))
            {
                throw new GeenZwangerschapMogelijkException("Mensen van hetzelfde geslacht kunnen niet opgeteld worden");
            }

            //default constructor Mens draagt zorg voor geboortedatum van 9 maanden +/- 2 weken
            Mens nieuwMens = new Mens();

            return nieuwMens;
        }

        /// <summary>
        /// Een nieuwe geboortedatum is 9 maanden van nu,
        /// +/- een x-aantal dagen binnen periode van 2 weken.
        /// </summary>
        /// <returns></returns>
        private static DateTime getNieuweGeboorteDatum()
        {
            DateTime nieuweGeboorteDatum = DateTime.Today;

            Random rand = new Random();
            int afwijkingInDagen = rand.Next(-14, 14);

            nieuweGeboorteDatum = nieuweGeboorteDatum.AddMonths(9).AddDays(afwijkingInDagen);

            return nieuweGeboorteDatum;
        }

        public string fillupBsn(string bsn)
        {
            if (bsn.Length < 15)
            {
                //String is minder dan 15 tekens lang, aanvullen met 0-en tot een lengte van 15
                for (int i = bsn.Length; i < 15; i++)
                {
                    bsn = "0" + bsn;
                }
            }

            return bsn;
        }

        //
        // Getters en Setters
        //

        public String Naam
        {
            set
            {
                this.naam = value;
            }
            get
            {
                return this.naam;
            }
        }

        public DateTime Geboortedatum
        {
            set
            {
                this.geboortedatum = value;
            }
            get
            {
                return this.geboortedatum;
            }
        }

        public string Bsn
        {
            private set
            {
                if(this.bsnRegex.IsMatch(value))
                {
                    // String bestaat enkel uit cijfer 0 tot en met 9, en is tussen de 1 en 15 cijfers lang
                    this.bsn = Int64.Parse(value);
                }
            }
            get
            {
                string returnBsn = this.bsn.ToString();
                if (!this.bsnRegex.IsMatch(returnBsn))
                {
                    return "Incorrect BSN-number";
                }

                returnBsn = fillupBsn(returnBsn);

                return returnBsn;
            }
        }

        public Sexe Geslacht
        {
            set
            {
                this.geslacht = value;
            }
            get
            {
                return this.geslacht;
            }
        }
    }
}
